#include "umsdatabase.h"
#include <QtXml>

//#include "http.h"
#define DEBUG_WS 0
UMSDatabase::UMSDatabase(const QString &server,int port)
{
	_server = server;
	//_server = "150.150.112.33";
	_port = port;
	_http = 0;
	_isOpened = false;
}

void UMSDatabase::setHost(const QString &addr)
{
	_server = addr;
}
bool UMSDatabase::open(const QString &user,const QString &passwd)
{
        qDebug() << "open"<<user<<passwd;
	_user = user;
	_lastError = QString();
	if(_http) delete _http;
	_http = new Http;
	_http->setHost(_server,_port);
	_http->setUser(user,passwd);
	_http->addHeaderVariable("User-Agent","UMSAccessModule_cpp/0.01");
	_http->get("/index.html");
	
	if(!_http->lastError().isNull()){
		_lastError = _http->lastError();
		return false;
	}
	if(_http->lastQueryResultCode()>=300 && _http->lastQueryResultCode()!=404){
		_lastError = trUtf8("Ошибка аутентификации %1. Неправильное имя пользователя или пароль.").arg(_http->lastQueryResultCode());
		return false;
	}
	_isOpened = true;
        return _isOpened;
}

QString UMSDatabase::lastError()
{
	return _lastError;
}

bool UMSDatabase::exec(const QString &query)
{
	_lastError = QString();
	_doc.clear();
	_currentVector.clear();
	checkSelectDatabase(query);
	_rawdata = sendQuery(soapXml(query).toUtf8());
	//qDebug() << Q_FUNC_INFO << _rawdata;
	QString str = QString::fromUtf8(_rawdata);
	QString op = "<query";
	//qDebug() << Q_FUNC_INFO << str.left(op.count());
	//qDebug() << Q_FUNC_INFO << str.simplified().left(op.count());
	if(str.simplified().left(op.count())==op){
		procData(str);//str.right(str.count()));
	}	
	return true;
}


QByteArray UMSDatabase::sendQuery(const QByteArray &data)
{
	if(!_isOpened) return QByteArray();
	if(!_http) return QByteArray();
	
	_http->setContentType("application/soap+xml; charset=UTF-8");
	_http->addHeaderVariable("Accept","text/xml, application/xml");	
	_http->setBody(data);	
	QByteArray rawdata = _http->post("/");	
	
	//qDebug() << Q_FUNC_INFO << "rawdata" << rawdata;
	if(!_http->lastError().isNull()){
		qWarning() << Q_FUNC_INFO << "lastError is not null";
		_lastError = _http->lastError();
		return QByteArray();
	}
	if(_http->lastQueryResultCode()>=300){
		qWarning() << Q_FUNC_INFO << "result code is"<<_http->lastQueryResultCode();
		_lastError = QString::number(_http->lastQueryResultCode())+"\r\n"+_rawdata;
		return QByteArray();
	}
	
	return rawdata;
}

int UMSDatabase::answerCode()
{
	if(!_http){
		_lastError = trUtf8("Отсутствует соединение");
		return 0;
	}
	return _http->lastQueryResultCode();
}

void UMSDatabase::procData(QString data)
{
	data = "<ums>"+data+"</ums>";
	///qDebug() << data;
	QString emg;
	int line;
	int column;
	_lastError = QString();
	if(!_doc.setContent(data,&emg,&line,&column)){
		_lastError = trUtf8("Ошибка внутреннего формата данных: %1 строка %2 колонка %3").arg(emg).arg(line).arg(column);
		qWarning() << Q_FUNC_INFO << _lastError;
		return;
	}
}

bool UMSDatabase::next()
{
	if(_currentVector.isNull()){
		//qDebug() << Q_FUNC_INFO << _doc.toString();
		QDomElement root = _doc.firstChildElement("ums");
		//qDebug() << Q_FUNC_INFO << root.isNull();		
		root = root.firstChildElement("query");
		while(!root.isNull()){
			if(root.attribute("type").left(6)=="select") break;
			root = root.nextSiblingElement("query");
		}
		//qDebug() << Q_FUNC_INFO << root.isNull();		
		//qDebug() << Q_FUNC_INFO << root.isNull();
		setCurrentVector(root.firstChildElement("cube"));
		//qDebug() << Q_FUNC_INFO << _currentVector.isNull();
	}else{
		setCurrentVector(_currentVector.nextSiblingElement("cube"));
	}
	return !_currentVector.isNull();
}

void UMSDatabase::first()
{
	while(!_currentVector.isNull()){
		setCurrentVector(_currentVector.previousSiblingElement("cube"));
	}
}

bool UMSDatabase::prev()
{
	if(_currentVector.isNull()){
		QDomElement root = _doc.firstChildElement("ums");
		//qDebug() << Q_FUNC_INFO << root.isNull();
		root = root.lastChildElement("query");
		//qDebug() << Q_FUNC_INFO << root.isNull();
		setCurrentVector(root.lastChildElement("cube"));
		//qDebug() << Q_FUNC_INFO << _currentVector.isNull();
		
	}else{
		setCurrentVector(_currentVector.previousSiblingElement("cube"));
	}
	return !_currentVector.isNull();
}

QDomElement UMSDatabase::vector()
{	
	return _currentVector;
}

QString UMSDatabase::soapXml(const QString &query)
{
	QDomDocument doc;
	QDomElement root = doc.createElement("env:Envelope");
	root.setAttribute("xmlns:env","http://www.w3.org/2003/05/soap-envelope");
	QDomElement header = doc.createElement("env:Header");
	QDomElement body   = doc.createElement("env:Body");
	root.appendChild(header);
	root.appendChild(body);
	header.appendChild(doc.createElement("umsMQLQuery"));
	QDomElement qteg = doc.createElement("query");
	QDomCDATASection cdata = doc.createCDATASection(query);
	qteg.appendChild(cdata);
	body.appendChild(qteg);
	doc.appendChild (root);
	return "<?xml version=\"1.0\"?>"+doc.toString(0);
}

QString UMSDatabase::soapXmlCommand(const QString &command,const QString &dbname,const QString &content)
{
	QDomDocument doc;
	QDomElement root = doc.createElement("env:Envelope");
	root.setAttribute("xmlns:env","http://www.w3.org/2003/05/soap-envelope");
	QDomElement header = doc.createElement("env:Header");
	QDomElement body   = doc.createElement("env:Body");
	root.appendChild(header);
	root.appendChild(body);
	QDomElement cmd = doc.createElement(command);	
	header.appendChild(cmd);
	if(!dbname.isEmpty()){
		QDomElement qteg = doc.createElement("ums");
		qteg.setAttribute("name",dbname);
		body.appendChild(qteg);
	}
	doc.appendChild (root);
	return "<?xml version=\"1.0\"?>"+doc.toString(0);
}

QString UMSDatabase::soapXmlCommandSetStruct(const QDomDocument &xdoc)
{
	QDomDocument doc;
	QDomElement root = doc.createElement("env:Envelope");
	doc.appendChild (root);
	root.setAttribute("xmlns:env","http://www.w3.org/2003/05/soap-envelope");
	QDomElement header = doc.createElement("env:Header");
	QDomElement body   = doc.createElement("env:Body");
	root.appendChild(header);
	root.appendChild(body);
	QDomElement cmd = doc.createElement("m:putScheme");	
	header.appendChild(cmd);
	
	QDomElement docElem = xdoc.documentElement();
	//QDomNode dnode = xdoc.firstChildNode();
	body.appendChild(docElem);
	
	
	return "<?xml version=\"1.0\"?>"+doc.toString(0);
}



QByteArray UMSDatabase::rawData()
{
	return _rawdata;
}

QString UMSDatabase::server()
{
	return _server;
}

QString UMSDatabase::user()
{
	return _user;
}

QString UMSDatabase::lastDatabase()
{
	return _lastDatabase;
}

void UMSDatabase::checkSelectDatabase(const QString &query)
{
	QRegExp re("^USE \"(.*)\";");
	re.setCaseSensitivity(Qt::CaseInsensitive);
	if(re.indexIn(query)!=-1){
		_lastDatabase = re.cap(1);
		if(_lastDatabase.indexOf("\"")>0)
			_lastDatabase = _lastDatabase.left(_lastDatabase.indexOf("\""));
		//qDebug() << re.caps(1);
	}
}

char *UMSDatabase::databaseStruct(const QString &name)
{
    return sendQuery(soapXmlCommand("m:getScheme",name).toUtf8()).data();
        /*QDomDocument doc;
	doc.setContent(sendQuery(soapXmlCommand("m:getScheme",name).toUtf8()));	
        return doc;*/
}

void UMSDatabase::sendDatabaseStruct(const QDomDocument &doc)
{
	//qDebug() <<Q_FUNC_INFO<< soapXmlCommandSetStruct(doc).toUtf8();
	/*QFile file(qApp->applicationDirPath()+"/admin.log");
	file.open(QIODevice::WriteOnly);
	file.write(soapXmlCommandSetStruct(doc).toUtf8());
	file.write("\n===============================\n");
	file.write(soapXmlCommandSetStruct(doc).toUtf8());
	file.close();*/
	
	sendQuery(soapXmlCommandSetStruct(doc).toUtf8());
	// doc после выполнения soapXmlCommandSetStruct очищается (!?)
}

QString UMSDatabase::uin()
{
	return _data.uin();
}

QString UMSDatabase::value(const QString &name)
{
	QStringList values = _data.values(name);
	if(values.count()==0) return QString();
	return _data.values(name).at(0);
}

QStringList UMSDatabase::values(const QString &name)
{
	return _data.values(name);
}

void UMSDatabase::setCurrentVector(QDomElement vec)
{
	_currentVector = vec;
	_data.setVector(_currentVector);
}
